package cn.wf.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @Description  Hystrix组件测试(雪崩效应:多级服务调用，一个服务挂了，导致很多服务都挂了)
 * @Author 万飞
 * @Date 2018/8/19 10:28
 */
@RestController
@DefaultProperties(defaultFallback = "defaultFallback")  //默认提供方法
public class HystrixController {

    //服务降级
//    @HystrixCommand

//    @HystrixCommand(fallbackMethod = "fallback")  （目标服务不能正常提供访问触发）

//    @HystrixCommand(commandProperties = {
//            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
//    })  //超时配置 在请求方法里默认超时时间是1s，如果超时就触发降级，上面设置了3秒


    //断路器过程：下面三个参数是控制断路器的关键参数
    //设置一个时钟选项，默认的时钟达到一个时间进入半熔断状态，sleepWindowIn时间窗口有一个时间范围
    //当断路器打开，对主逻辑机制进行熔断之后，hystrix会启动一个休眠时间窗，在这个时间窗内，降级逻辑
    //临时成为主逻辑，当休眠时间窗到期，断路器进入半开状态，释放一次请求到原来的主逻辑上，如果此次请求
    //正常返回，那么断路器将继续闭合，主逻辑恢复，如果此次请求依然有问题，断路器将继续进入打开状态，
    // 休眠时间窗重新计时
    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),  //设置熔断open
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// 设置断路器滚动中最小请求数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),  //10秒,休眠时间窗
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")  //断路器打开的错误百分比条件(10次有7次，70%>60%，断路器会打开)
    })

    @GetMapping(value = "/getProductInfoList")
    public String getProductInfoList(@RequestParam("number") Integer number) {  //@RequestParam("number") Integer number是为了测试熔断，传奇数和偶数
        //偶数直接return，奇数会去访问listForOrder(sleep了2秒，默认1秒，超时会触发降级)，所以这里偶数可以正常，奇数降级
        //当访问奇数接口在浏览器一直刷新，过一会儿访问偶数接口会触发降级（熔断），刷新偶数接口触发降级后，刷新一会儿后熔断小时，偶数接口又好了
        if(number % 2 == 0) {
            return "success";
        }
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8038/product/listForOrder", Arrays.asList("157875227953464068"),
                String.class);  //restTemplate  http请求都是返回String，前面写类是自动转了一次

//        throw new RuntimeException("发生异常了");  //这样也会触发fallback,并发太高，数据库连接数太多也可以这样来触发降级
    }

    public String fallback() {
        return "太拥挤了，请稍后再试...";
    }

    public String defaultFallback() {
        return "默认提示: 太拥挤了，请稍后再试...";
    }

}
